/*
 * Object   : CNetMgr
 * Type     : Backend
 *
 * Narrator : Kamran H. Khan 
 * Email    : KAMRAN.KHAN@MaximaLabssolutions.com, KAMRANHK@gmail.com
 * 
 * Copyright :
 *            MaximaLabs Solutions (R) 2009
 * 
 * 
 * Description: 
 * Provides TCP server/client functionalities. object factory pattern
 * 
 * Revision History:
 * 
 * Date(MMM/dd/yy)      Owner           Description
 * ----------------------------------------------------------------------------------------------------------------------------------------------
 * May/30/09            Kamran H. Khan  Added skeleton code
 * May/30/09            Kamran H. Khan  Added more methods
 * 
 * 
 * 
*/


using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using Maxima.Common;
//using System.Windows.Forms;


namespace Maxima.Communicator
{
    public class CNetMgr //: Control
    {
        CServer m_theServer = null;
        CClient m_theClient = null;

        protected const int READ_BUFFER_MAX_SIZE = 1024;// Client size
        //protected int MSG_SIZE_1KB = 1024; //Server size
        protected int NO_OF_MAX_CLIENTS_SUPPORTED = 10;
        protected string CLOSE_CONNECTION_REQUEST_CODE = "logout";

        public delegate void StatusChangeEventHandler(string strData, bool bIsServer);
        public event StatusChangeEventHandler OnStatusChange;


        private bool m_bIsServer;
        public bool IsServer
        {
            get { return m_bIsServer; }
            set { m_bIsServer = value; }
        }

        private string m_strIP;
        [Category("Settings")]
        [Description("IP Address")]
        [BrowsableAttribute(true)]
        public string IP
        {
            get { return m_strIP; }
            set { m_strIP = value; }
        }

        private int m_nPort;

        [Category("Settings")]
        [Description("Port")]
        [BrowsableAttribute(true)]
        public int Port
        {
            get { return m_nPort; }
            set { m_nPort = value; }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="CNetMgr"/> class.
        /// </summary>
        /// <param name="strIP">The STR IP.</param>
        /// <param name="nPort">The n port.</param>
        /// <param name="bRunAsServer">if set to <c>true</c> [b run as server].</param>
        public CNetMgr(string strIP, int nPort, bool bRunAsServer) 
        {
            CLogger.GetInstance().Debug(this.GetType().Name, System.Reflection.Emit.MethodBuilder.GetCurrentMethod().Name, "Middleware Simulator [Version v2.0]");
            CLogger.GetInstance().Debug(this.GetType().Name, System.Reflection.Emit.MethodBuilder.GetCurrentMethod().Name, "(c) Copyright MaximaLabs 2012");

            CLogger.GetInstance().Debug(this.GetType().Name, System.Reflection.Emit.MethodBuilder.GetCurrentMethod().Name, "Starting network manager...");
            
            m_bIsServer = bRunAsServer;
            m_nPort = nPort;
            m_strIP = strIP;

            CLogger.GetInstance().Debug(this.GetType().Name, System.Reflection.Emit.MethodBuilder.GetCurrentMethod().Name, "Initialization success.", System.Diagnostics.EventLogEntryType.Information);

        }

        /// <summary>
        /// M_thes the client_ on status change.
        /// </summary>
        /// <param name="strData">The STR data.</param>
        void m_theClient_OnStatusChange(string strData)
        {
            CLogger.GetInstance().Debug(this.GetType().Name, System.Reflection.Emit.MethodBuilder.GetCurrentMethod().Name, "Inside", System.Diagnostics.EventLogEntryType.Information);
            
            if (OnStatusChange != null)
                OnStatusChange(strData, false);

            CLogger.GetInstance().Debug(this.GetType().Name, System.Reflection.Emit.MethodBuilder.GetCurrentMethod().Name, "End", System.Diagnostics.EventLogEntryType.Information);

        }

        /// <summary>
        /// M_thes the server_ on status change.
        /// </summary>
        /// <param name="strData">The STR data.</param>
        void m_theServer_OnStatusChange(string strData)
        {
            CLogger.GetInstance().Debug(this.GetType().Name, System.Reflection.Emit.MethodBuilder.GetCurrentMethod().Name, "Inside", System.Diagnostics.EventLogEntryType.Information);

            if (OnStatusChange != null)
                OnStatusChange(strData, true);
            CLogger.GetInstance().Debug(this.GetType().Name, System.Reflection.Emit.MethodBuilder.GetCurrentMethod().Name, "End", System.Diagnostics.EventLogEntryType.Information);
        }

        /// <summary>
        /// Starts this instance.
        /// </summary>
        public void Start()
        {
            CLogger.GetInstance().Debug(this.GetType().Name, System.Reflection.Emit.MethodBuilder.GetCurrentMethod().Name, "Inside method", System.Diagnostics.EventLogEntryType.Information);
            if (m_bIsServer)
            {
                //Start server.
                m_theServer = new CServer(m_strIP, m_nPort);
                m_theServer.OnStatusChange += new CServer.StatusChangeEventHandler(m_theServer_OnStatusChange);
                m_theServer.Start();
            }
            else
            {
                m_theClient = new CClient(m_strIP, m_nPort);
                m_theClient.OnStatusChange += new CClient.StatusChangeEventHandler(m_theClient_OnStatusChange);
                m_theClient.Start();
            }
            CLogger.GetInstance().Debug(this.GetType().Name, System.Reflection.Emit.MethodBuilder.GetCurrentMethod().Name, "End", System.Diagnostics.EventLogEntryType.Information);
        }

        /// <summary>
        /// Stops this instance.
        /// </summary>
        public void Stop()
        {
            CLogger.GetInstance().Debug(this.GetType().Name, System.Reflection.Emit.MethodBuilder.GetCurrentMethod().Name, "Inside", System.Diagnostics.EventLogEntryType.Information);
            if (m_bIsServer && m_theServer != null)
            {
                m_theServer.Stop();
            }
            else
            {
                if (m_theClient != null)
                {
                    CLogger.GetInstance().Debug(this.GetType().Name, System.Reflection.Emit.MethodBuilder.GetCurrentMethod().Name, "Logging out", System.Diagnostics.EventLogEntryType.Information);
                    //Send("logout");
                    Send("0000");
                    m_theClient.Stop();
                }
            }
            CLogger.GetInstance().Debug(this.GetType().Name, System.Reflection.Emit.MethodBuilder.GetCurrentMethod().Name, "End", System.Diagnostics.EventLogEntryType.Information);

        }

        /// <summary>
        /// Determines whether the specified b server is connected.
        /// </summary>
        /// <param name="bServer">if set to <c>true</c> [b server].</param>
        /// <returns>
        /// 	<c>true</c> if the specified b server is connected; otherwise, <c>false</c>.
        /// </returns>
        public bool IsConnected(bool bServer)
        {
            CLogger.GetInstance().Debug(this.GetType().Name, System.Reflection.Emit.MethodBuilder.GetCurrentMethod().Name, "Inside", System.Diagnostics.EventLogEntryType.Information);
            if (bServer)
            {
                return m_theServer.IsConnected;
            }
            else
            {
                return m_theClient.IsConnected;
            }
            CLogger.GetInstance().Debug(this.GetType().Name, System.Reflection.Emit.MethodBuilder.GetCurrentMethod().Name, "End", System.Diagnostics.EventLogEntryType.Information);
        }

        /// <summary>
        /// Sends the specified STR data.
        /// </summary>
        /// <param name="strData">The STR data.</param>
        /// <returns></returns>
        public int Send(string strData)
        {
            CLogger.GetInstance().Debug(this.GetType().Name, System.Reflection.Emit.MethodBuilder.GetCurrentMethod().Name, "Inside", System.Diagnostics.EventLogEntryType.Information);

            CLogger.GetInstance().Debug(this.GetType().Name, System.Reflection.Emit.MethodBuilder.GetCurrentMethod().Name, "Sending message", System.Diagnostics.EventLogEntryType.Information);
            int nBytesSent = 0;
            if (m_bIsServer)
            {
                
                nBytesSent = m_theServer.Send(strData);
            }
            else
            {
                if (!m_theClient.IsConnected)
                {
                    CLogger.GetInstance().Debug(this.GetType().Name, System.Reflection.Emit.MethodBuilder.GetCurrentMethod().Name, "Disconnected, stopping.", System.Diagnostics.EventLogEntryType.Information);
                    m_theClient.Stop();
                    m_theClient.Start();
                    CLogger.GetInstance().Debug(this.GetType().Name, System.Reflection.Emit.MethodBuilder.GetCurrentMethod().Name, "Disconnected, restarted.", System.Diagnostics.EventLogEntryType.Information);
                }
                
                    
                nBytesSent = m_theClient.Send(strData);
            }

            CLogger.GetInstance().Debug(this.GetType().Name, System.Reflection.Emit.MethodBuilder.GetCurrentMethod().Name, "End", System.Diagnostics.EventLogEntryType.Information);
            return nBytesSent;
        }
    }
}
